package com.example.service.Impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.enums.KeyEnum;
import com.example.common.websocket.WebSocketServe;
import com.example.context.BaseContext;
import com.example.mapper.*;
import com.example.pojo.dto.JoinDTO;
import com.example.pojo.entity.*;
import com.example.pojo.utils.ApprocalPageResult;
import com.example.pojo.utils.ProcIns;
import com.example.pojo.utils.SendMessage;
import com.example.pojo.utils.TaskInfo;
import com.example.pojo.vo.ApprovalVO;
import com.example.service.ApprovalService;
import com.example.utils.HttpsUtil;
import com.example.utils.SendMessageUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TODO
 *
 * @author ding
 * @since 2024/7/13
 */
@Service
@Slf4j
public class ApprovalServiceImpl extends ServiceImpl<ApprovalMapper, Approval>implements ApprovalService {

    @Autowired
    private ApprovalMapper approvalMapper;

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private TemplateMapper templateMapper;

    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private WebSocketServe webSocketServe;

    @Autowired
    private TeamMapper teamMapper;

    @Autowired
    private SendMessageUtils sendMessageUtils;

    /**
     * 分页获取审批信息
     */
    public ApprocalPageResult selectPage(Integer pageNum, Integer pageSize) {
        Long currentId = BaseContext.getCurrentId();
        Admin admin = adminMapper.selectById(currentId.intValue());
        String userId = admin.getName();

        Map<String, String> map = new HashMap<>();
        map.put("userId", userId);
        map.put("pageNum", String.valueOf(pageNum));
        map.put("pageSize", String.valueOf(pageSize));
        HttpsUtil.sendGet("http://localhost:9091/engine/getMyTodo", map);

        //获取redis中的接送字符串
        String proListString = (String)redisTemplate.opsForValue().get("MyTodo" + "_" + userId + "_" + pageNum + "_" + pageSize);
        List<ProcIns> procInsList = JSON.parseArray(proListString, ProcIns.class);
        redisTemplate.delete("MyTodo" + "_" + userId + "_" + pageNum + "_" + pageSize);

        for (ProcIns procIns : procInsList) {
            Approval approval = approvalMapper.selectOne(new LambdaQueryWrapper<Approval>().eq(Approval::getProcInstId, procIns.getProInsId()));
            //若申请中存在项目id，则该申请为项目申请，存在项目id
            if (ObjectUtil.isNotEmpty(approval.getProjectId())) {
                procIns.setProjectId(approval.getProjectId());
            }
            if(ObjectUtil.isNotEmpty(approval.getTeamId())){
                procIns.setReason(approval.getDescription());
            }
            procIns.setApplicantId(admin.getId());
            procIns.setStatus(approval.getStatus());
            procIns.setType(approval.getType());

            //为流程设置审批人信息
            Template template = templateMapper.selectOne(new LambdaQueryWrapper<Template>().eq(Template::getProcDefId, procIns.getProDefId()));
            String person = template.getPerson();
            String[] split = person.split(",");
            if (split.length > 0) {
                Admin admin1 = adminMapper.selectById(Integer.parseInt(split[0]));
                TaskInfo taskInfo = new TaskInfo();
                taskInfo.setUserName(admin1.getName());

                taskInfo.setTaskStatus(procIns.getTasks().get(0).getTaskStatus());
                taskInfo.setTaskId(procIns.getTasks().get(0).getTaskId());
                if (procIns.getTasks().get(0).getMessage() != null){
                    taskInfo.setMessage(procIns.getTasks().get(0).getMessage());
                }
                if (procIns.getTasks().get(0).getTaskTime() != null){
                    taskInfo.setTaskTime(procIns.getTasks().get(0).getTaskTime());
                }
                taskInfo.setPhone(admin1.getPhone());
                procIns.setPerson1(taskInfo);

                //如果任务节点状态节点为拒绝，那么就可以更新状态
                if (procIns.getTasks().get(0).getTaskStatus().equals("任务状态:驳回")) {
                    //如果当前审批是项目申请 更改对应项目的审批状态
                    if (ObjectUtil.isNotEmpty(approval.getProjectId())) {
                        Project project = projectMapper.selectById(approval.getProjectId());
                        project.setStatus(2);
                        projectMapper.updateById(project);
                    }
                }
            }
            if (split.length > 1) {
                Admin admin2 = adminMapper.selectById(Integer.parseInt(split[1]));
                TaskInfo taskInfo = new TaskInfo();
                taskInfo.setPhone(admin2.getPhone());
                taskInfo.setUserName(admin2.getName());
                if (procIns.getTasks().size() > 1) {
                    taskInfo.setTaskStatus(procIns.getTasks().get(1).getTaskStatus());
                    taskInfo.setTaskId(procIns.getTasks().get(1).getTaskId());
                    if (procIns.getTasks().get(1).getMessage() != null){
                        taskInfo.setMessage(procIns.getTasks().get(1).getMessage());
                    }
                    if (procIns.getTasks().get(1).getTaskTime() != null){
                        taskInfo.setTaskTime(procIns.getTasks().get(1).getTaskTime());
                    }
                }
                procIns.setPerson2(taskInfo);

                //如果任务节点状态节点为拒绝，那么就可以更新状态
                if (procIns.getTasks().get(0).getTaskStatus().equals("任务状态:驳回")) {
                    //如果当前审批是项目申请 更改对应项目的审批状态
                    if (ObjectUtil.isNotEmpty(approval.getProjectId())) {
                        Project project = projectMapper.selectById(approval.getProjectId());
                        project.setStatus(2);
                        projectMapper.updateById(project);
                    }
                }
            }
            if (split.length > 2) {
                Admin admin3 = adminMapper.selectById(Integer.parseInt(split[2]));
                TaskInfo taskInfo = new TaskInfo();
                taskInfo.setPhone(admin3.getPhone());
                taskInfo.setUserName(admin3.getName());
                if (procIns.getTasks().size() > 2) {
                    taskInfo.setTaskStatus(procIns.getTasks().get(2).getTaskStatus());
                    taskInfo.setTaskId(procIns.getTasks().get(2).getTaskId());
                    if (procIns.getTasks().get(2).getMessage() != null){
                        taskInfo.setMessage(procIns.getTasks().get(2).getMessage());
                    }
                    if (procIns.getTasks().get(2).getTaskTime() != null){
                        taskInfo.setTaskTime(procIns.getTasks().get(2).getTaskTime());
                    }
                }
                procIns.setPerson3(taskInfo);

                //如果任务节点状态节点为拒绝，那么就可以更新状态
                if (procIns.getTasks().get(0).getTaskStatus().equals("任务状态:驳回")) {
                    //如果当前审批是项目申请 更改对应项目的审批状态
                    if (ObjectUtil.isNotEmpty(approval.getProjectId())) {
                        Project project = projectMapper.selectById(approval.getProjectId());
                        project.setStatus(2);
                        projectMapper.updateById(project);
                    }
                }
            }
        }

        ApprocalPageResult result = ApprocalPageResult.builder()
                .records(procInsList)
                .total(procInsList.size())
                .typeId(1)
                .build();

        return result;
    }

    /**
     * 我的处理
     */
    public ApprocalPageResult selectMyHandle(Integer pageNum, Integer pageSize) {
        Long currentId = BaseContext.getCurrentId();
        Admin admin = adminMapper.selectById(currentId.intValue());
        String userId = admin.getName();

        //设置参数
        Map<String, String> map = new HashMap<>();
        map.put("userId", userId);
        map.put("pageNum", String.valueOf(pageNum));
        map.put("pageSize", String.valueOf(pageSize));
        //调用另一个项目的接口
        HttpsUtil.sendGet("http://localhost:9091/engine/getMyHandle", map);

        //从redis中获取存储的相关信息
        String proListString = (String) redisTemplate.opsForValue().get("MyHandle" + "_" + userId+"_"+pageNum+"_"+pageSize);
        List<ProcIns> procInsList = JSON.parseArray(proListString, ProcIns.class);

        for (ProcIns procIns : procInsList) {
            //获取该流程对应的审批
            Approval approval = approvalMapper.selectOne(new LambdaQueryWrapper<Approval>().eq(Approval::getProcInstId, procIns.getProInsId()));
            if (procIns.getTasks().size() > 0) {
                procIns.setPerson1(procIns.getTasks().get(0));
            }
            if (procIns.getTasks().size() > 1) {
                procIns.setPerson2(procIns.getTasks().get(1));
            }
            if (procIns.getTasks().size() > 2) {
                procIns.setPerson3(procIns.getTasks().get(2));
            }

            if (ObjectUtil.isNotEmpty(approval.getProjectId())) {
                procIns.setProjectId(approval.getProjectId());
            }
            procIns.setStatus(approval.getStatus());
            procIns.setType(approval.getType());
            procIns.setApplicantId(approval.getApplicantId());
            procIns.setTeamId(approval.getTeamId());

        }

        ApprocalPageResult result = ApprocalPageResult.builder()
                .records(procInsList)
                .total(procInsList.size())
                .typeId(2)
                .build();

        return result;
    }

    /**
     * 我的请求
     */
    @Override
    public ApprocalPageResult selectMySubmit(Integer pageNum, Integer pageSize) {
        Long currentId = BaseContext.getCurrentId();
        Admin admin = adminMapper.selectById(currentId.intValue());
        String userId = admin.getName();

        //设置参数
        Map<String, String> map = new HashMap<>();
        map.put("userId", userId);
        map.put("pageNum", String.valueOf(pageNum));
        map.put("pageSize", String.valueOf(pageSize));
        //调用另一个项目的接口
        HttpsUtil.sendGet("http://localhost:9091/engine/getMySubmit", map);

        //从redis中获取存储的相关信息
        String proListString = (String) redisTemplate.opsForValue().get("MySubmit" + "_" + userId+"_"+pageNum+"_"+pageSize);
        List<ProcIns> procInsList = JSON.parseArray(proListString, ProcIns.class);

        for (ProcIns procIns : procInsList) {
            Approval approval = approvalMapper.selectOne(new LambdaQueryWrapper<Approval>().eq(Approval::getProcInstId, procIns.getProInsId()));
            if (procIns.getTasks().size() > 0) {
                procIns.setPerson1(procIns.getTasks().get(0));
            }
            if (procIns.getTasks().size() > 1) {
                procIns.setPerson2(procIns.getTasks().get(1));
            }
            if (procIns.getTasks().size() > 2) {
                procIns.setPerson3(procIns.getTasks().get(2));
            }
            procIns.setStatus(approval.getStatus());
            procIns.setType(approval.getType());
            procIns.setApplicantId(approval.getApplicantId());
            procIns.setStatus(approval.getStatus());

        }

        ApprocalPageResult result = ApprocalPageResult.builder()
                .records(procInsList)
                .total(procInsList.size())
                .typeId(3)
                .build();

        return result;
    }

    /**
     * 进行审批
     */
    public void apply(ApprovalVO approvalVO) {
        log.info("进行审批{}", approvalVO);

        String person = templateMapper.selectOne(new LambdaQueryWrapper<Template>().eq(Template::getProcDefId, approvalVO.getProDefId())).getPerson();
        String[] split = person.split(",");
        String name = adminMapper.selectById(Integer.parseInt(split[approvalVO.getCurrent()-1])).getName();
        Integer userId = BaseContext.getCurrentId().intValue();

        Approval approval = approvalMapper.selectOne(new LambdaQueryWrapper<Approval>()
                .eq(Approval::getProcInsList, approvalVO.getProInsId()));

        Boolean flag = false;
        if (approvalVO.getStatus().equals("1")){
            flag = true;
        }

        //当审批达到最后一个审批人，可以判断审批是否通过
        if (approvalVO.getCurrent() == split.length) {
            if (flag) {
                //审核通过
                approval.setStatus("1");
                approvalMapper.updateById(approval);

                //审批有项目id，则为项目申请
                if (ObjectUtil.isNotEmpty(approval.getProjectId())){
                    Project project = projectMapper.selectById(approval.getProjectId());
                    project.setStatus(1);
                    projectMapper.updateById(project);
                    redisTemplate.delete(KeyEnum.PROJECT_UNDE_UNCOMP);
                }
                //审批有团队id，则为入队申请
                if (ObjectUtil.isNotEmpty(approval.getType())){
                    //设置申请人的id为空qu
                    Admin applicant = adminMapper.selectById(approval.getApplicantId());
                    adminMapper.update(new LambdaUpdateWrapper<Admin>()
                            .set(Admin::getTeamId, approval.getTeamId())
                            .eq(Admin::getId, applicant.getId()));
                }



            }
        }

        if (!flag){
            //审核不通过
            approval.setStatus("2");
            approvalMapper.updateById(approval);

            if (ObjectUtil.isNotEmpty(approval.getProjectId())){
                Project project = projectMapper.selectById(approval.getProjectId());
                project.setStatus(2);
                projectMapper.updateById(project);
                redisTemplate.delete(KeyEnum.PROJECT_UNDE_UNCOMP);
            }
        }

        //获取申请人信息
        Admin applicant = adminMapper.selectById(approval.getApplicantId());
        String content = "尊敬的" + applicant.getName() + ",你的请求已被处理，请上线观看";
        SendMessage sendMessage = SendMessage.builder()
                .subject("请求处理")
                .to(applicant.getEmail())
                .content(content)
                .build();
        sendMessageUtils.sendMessage(sendMessage);

        Map<String, Object> map = new HashMap<>();
        map.put("procxInstId", approvalVO.getProInsId());
        map.put("flag", flag);
        map.put("userId", name);
        map.put("msg", approvalVO.getMsg());
        HttpsUtil.sendPost("http://localhost:9091/engine/apploy", map);

        //将对应的任务从redis中删除
        redisTemplate.opsForSet().remove(KeyEnum.TASK + "_" + userId, approvalVO.getProInsId());

        if (approvalVO.getCurrent() < split.length) {
            //添加新的审批任务
            Map wbMap = new HashMap();
            wbMap.put("type", 1);
            wbMap.put("authenticate", adminMapper.selectById(approval.getApplicantId()).getName());
            wbMap.put("procInstId", approvalVO.getProInsId());
            String json = JSON.toJSONString(wbMap);
            webSocketServe.sendToClient(json, split[approvalVO.getCurrent()]);

            //在redis中添加新的任务
            redisTemplate.opsForSet().add(KeyEnum.TASK + "_" + split[approvalVO.getCurrent()], approvalVO.getProInsId());
        }
    }


    /**
     * 新增入队申请
     */
    @Override
    public void addJoinTeam(JoinDTO joinDTO) {
        Template template = templateMapper.selectOne(new LambdaQueryWrapper<Template>().eq(Template::getName, "入职申请"));
        Admin admin = adminMapper.selectById(joinDTO.getApplicantId());
        String person = template.getPerson();
        StringBuilder sb = new StringBuilder("");
        String[] split = person.split(",");
        for (int i = 1; i <= split.length; i++) {
            Admin adm = adminMapper.selectById(Integer.valueOf(split[i - 1]));
            sb.append(adm.getName()).append("-");
        }
        String variables = sb.toString();
        Map<String, Object> map = new HashMap<>();
        map.put("authenticate", admin.getName());
        map.put("proDefId", template.getProcDefId());
        map.put("variables", variables);
        map.put("UID", admin.getId());

        String procInstId = HttpsUtil.sendPost("http://localhost:9091/engine/start", map);

        Approval approval =Approval.builder()
                .file(joinDTO.getFile())
                .type("入职申请")
                .applicantId(joinDTO.getApplicantId())
                .status("0")
                .teamId(joinDTO.getTeamId())
                .description(joinDTO.getReason())
                .procInstId(procInstId)
                .build();
        approvalMapper.insert(approval);
        redisTemplate.opsForSet().add("UPLOAD_db_img", joinDTO.getFile());

        Team team = teamMapper.selectById(joinDTO.getTeamId());

        //通过websocket向客户端浏览器推送消息，推送数据格式为JSON type approval content
        Map webMap = new HashMap();
        //审批类型 1：项目审批 2：采购审批 3：入队审批
        webMap.put("type", 3);
        webMap.put("authenticate", admin.getName());
        webMap.put("procInstId", procInstId);
        webMap.put("content", "施工队名称:" + team.getName());
        String json = JSON.toJSONString(webMap);
        webSocketServe.sendToClient(json, split[0]);
        //将待审批业务放于redis中
        redisTemplate.opsForSet().add(KeyEnum.TASK + "_" + split[0], procInstId);
    }
}
